package wechat

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"jk-time/webook/internal/domain"
	"jk-time/webook/internal/service"
	"jk-time/webook/pkg/migrator/events"
	"net/http"
	"net/url"
)

type WeChatService struct {
	appId     string
	appSecret string
	client    *http.Client
	srv       service.UserService
	prooducer events.Producer
}

func NewWeChatService(appId string, appSecret string, srv service.UserService) *WeChatService {
	return &WeChatService{
		appId:     appId,
		appSecret: appSecret,
		client:    http.DefaultClient,
		srv:       srv,
	}
}
func (w *WeChatService) AuthURL(ctx context.Context, state string) (string, error) {
	const urlPattern = "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s" +
		"&response_type=code&scope=snsapi_login&state=%s#wechat_redirect"
	redirect := viper.GetString("oauth.wechat")
	redirectURI := url.PathEscape(redirect)
	return fmt.Sprintf(urlPattern, w.appId, redirectURI, state), nil
}
func (w *WeChatService) VerifyCode(ctx context.Context, code string) (domain.Oauth2Info, error) {
	const targetPattern = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s" +
		"&code=%s&grant_type=authorization_code"
	target := fmt.Sprintf(targetPattern, w.appId, w.appSecret, code)
	//请求
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, target, nil)
	if err != nil {
		return domain.Oauth2Info{}, nil
	}
	//回应
	resp, err := w.client.Do(req)
	if err != nil {
		return domain.Oauth2Info{}, nil
	}

	var res Result
	//再读一遍，合计两遍
	//body,err := io.ReadAll(resp.Body)
	//json.Unmarshal(body,&res)

	err = json.NewDecoder(resp.Body).Decode(&res)
	if err != nil {
		return domain.Oauth2Info{}, nil
	}

	if res.ErrCode != 0 {
		return domain.Oauth2Info{}, fmt.Errorf("微信返回错误响应，错误码：%d，错误信息：%s", res.ErrCode, res.ErrMsg)
	}
	zap.L().Info("调用微信，拿到用户信息",
		zap.String("openId", res.OpenId), zap.String("unionId", res.UnionId))
	return domain.Oauth2Info{
		OpenId:  res.OpenId,
		UnionId: res.UnionId,
	}, nil
}
func (w *WeChatService) FindOrCreateByInfo(ctx context.Context, info domain.Oauth2Info) (domain.User, error) {
	return w.srv.FindOrCreateWechat(ctx, info)
}

type Result struct {
	AccessToken  string `json:"access_token"`  //token获取数据
	ExpiresIn    int64  `json:"expires_in"`    //过期时间
	RefreshToken string `json:"refresh_token"` //刷新token
	OpenId       string `json:"openid"`        //同一公司不同产品不同
	Scope        string `json:"scope"`
	UnionId      string `json:"unionId"` //公司下的id

	ErrCode int64  `json:"errcode"`
	ErrMsg  string `json:"errmsg"`
}
